package sk.ownage.p1.featurestore;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

import android.os.Environment;
import android.util.Log;

public class LandmarkReader {
	private final String TAG="LandmarkReader";
	private final String rootPath=Environment.getExternalStorageDirectory()+"/featureStore"+"/landmarks";
	private final int DIRECTORY_MAX=LandmarkStore.DIRECTORY_MAX;
	private String landmarkPath="";
	public final int WRONG_FILE=-1;
	public final int START_FILE=0;
	public final int NAME_READ_DONE=1;
	public final int CATEGORY_READ_DONE=2;
	public final int TIMESTAMP_READ_DONE=3;
	public final int DESCRIPTION_READ_DONE=4;
	public final int DESCRIPTION_EMPTY_READ_DONE=41;
	public final int NEW_LANDMARK=5;
	public final int LANDMARK_LATITUDE_READ_DONE=51;
	public final int LANDMARK_LONGITUDE_READ_DONE=52;
	public final int LANDMARK_ALTITUDE_READ_DONE=53;
	public final int LANDMARK_TIMESTAMP_READ_DONE=54;
	public final int END_FILE=6;
	private int readerState=0;
	private FileInputStream fis;
	private ObjectInputStream is;
	
	public LandmarkReader(int landmarkId){
		this(landmarkId,"");
	}
	
	public LandmarkReader(int landmarkId, String landmarkRootPath){
		int folderId=landmarkId/DIRECTORY_MAX;
		int fileId=landmarkId%DIRECTORY_MAX;
		String folderPath=(((folderId/100)>0)?"":"0")+(((folderId/10)>0)?"":"0")+folderId;
		String filePath=(((fileId/100)>0)?"":"0")+(((fileId/10)>0)?"":"0")+fileId;
		landmarkPath=((!landmarkRootPath.equals(""))?landmarkRootPath:rootPath)+"/"+folderPath+"/"+filePath+".bin";
		File landmarkFile=new File(landmarkPath);
		if(landmarkFile.exists()){
			try {
				fis = new FileInputStream(landmarkFile);
				is = new ObjectInputStream(new BufferedInputStream(fis));
					readerState=START_FILE;
			} catch (Exception e) {
				Log.d(TAG, e.toString());
				e.printStackTrace();
			}
		}
	}
	
	public String readName() throws Exception{
		String result="";
		if(readerState==START_FILE){
			try {
				if(is.readByte()==1){
					result=is.readUTF();
					readerState=NAME_READ_DONE;
				}
				else{
					readerState=WRONG_FILE;
				}
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		} 
		else{
			throw new Exception("Cannot read Name at this state!");
		}
	}
	
	public String readCategory() throws Exception{
		String result="";
		if(readerState==NAME_READ_DONE){
			try {
				if(is.readByte()==1){
					result=is.readUTF();
					readerState=CATEGORY_READ_DONE;
				}
				else{
					readerState=WRONG_FILE;
				}
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		} 
		else{
			throw new Exception("Cannot read Category name at this state!");
		}
	}
	
	public long readTimestamp() throws Exception{
		long result=0;
		if(readerState==CATEGORY_READ_DONE){
			try {
				if(is.readByte()==1){
					result=is.readLong();
					readerState=TIMESTAMP_READ_DONE;
				}
				else{
					readerState=WRONG_FILE;
				}
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		} 
		else{
			throw new Exception("Cannot read Timestamp at this state!");
		}
	}
	
	public String readDescription() throws Exception{
		String result="";
		if(readerState==TIMESTAMP_READ_DONE){
			try {
				byte nextByte=is.readByte();
				if(nextByte==1){
					result=is.readUTF();
					readerState=DESCRIPTION_READ_DONE;
				}
				else if(nextByte==0){
					readerState=DESCRIPTION_EMPTY_READ_DONE;//empty desc
				}
				else{
					readerState=WRONG_FILE;
				}
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}else{
			throw new Exception("Cannot read Description at this state!");
		}
	}
	
	public boolean hasLandmark() throws Exception{
		boolean result=false;
		if(readerState==DESCRIPTION_READ_DONE || readerState==DESCRIPTION_EMPTY_READ_DONE || readerState==LANDMARK_TIMESTAMP_READ_DONE){
			try {
				result=((byte)is.read()==1);
				if(result){
					readerState=NEW_LANDMARK;
				}
				else{
					readerState=END_FILE;
				}
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}
		else{
			throw new Exception("Cannot read NewTrack flag at this state!");
		}
	}
	
	public double readLandmarkLatitude() throws Exception{
		double result=0;
		if(readerState==NEW_LANDMARK){
			try {
				result=is.readDouble();
					readerState=LANDMARK_LATITUDE_READ_DONE;
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}
		else{
			throw new Exception("Cannot read landmark latitude at this state!");
		}
	}
	
	public double readLandmarkLongitude() throws Exception{
		double result=0;
		if(readerState==LANDMARK_LATITUDE_READ_DONE){
			try {
				result=is.readDouble();
					readerState=LANDMARK_LONGITUDE_READ_DONE;
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}
		else{
			throw new Exception("Cannot read landmark longitude at this state!");
		}
	}
	
	public double readLandmarkAltitude() throws Exception{
		double result=0;
		if(readerState==LANDMARK_LONGITUDE_READ_DONE){
			try {
				result=is.readDouble();
					readerState=LANDMARK_ALTITUDE_READ_DONE;
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}
		else{
			throw new Exception("Cannot read landmark longitude at this state!");
		}
	}
	
	public long readLandmarkTimestamp() throws Exception{
		long result=0;
		if(readerState==LANDMARK_ALTITUDE_READ_DONE){
			try {
				result=is.readLong();
					readerState=LANDMARK_TIMESTAMP_READ_DONE;
			} catch (Exception e) {
				Log.d(TAG,e.toString());
				e.printStackTrace();
			}
			return result;
		}
		else{
			throw new Exception("Cannot read landmark timestamp at this state!");
		}
	}
		
	public void stopReader(){
		try {
			is.close();
		} catch (IOException e) {
			Log.d(TAG, e.toString());
			e.printStackTrace();
		}
	}
	
	public void resetReader(){
		try {
			is.close();
			is = new ObjectInputStream(new BufferedInputStream(fis));
			readerState=START_FILE;
		} catch (IOException e) {
			Log.d(TAG, e.toString());
			e.printStackTrace();
		}
	}
}
